package xyz.xtt.exchange.service.impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import xyz.xtt.exchange.constants.ExchangeCache;
import xyz.xtt.exchange.entity.TblUserLike;
import xyz.xtt.exchange.mapper.TblUserLikeMapper;
import xyz.xtt.exchange.service.IInnerService;
import xyz.xtt.exchange.service.IUserLikeService;

/**
 * <p>
 * 用户点赞表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-12-30
 */
@Service
public class UserLikeServiceImpl extends ServiceImpl<TblUserLikeMapper, TblUserLike> implements IUserLikeService {
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	@Autowired
	private IInnerService iInnerService;

	@Override
	public Boolean like(Long uid, String goodsId, int status) {
		if (status == 0) {
			return addLike(uid, goodsId);
		}

		if (status == 1) {
			return delLike(uid, goodsId);
		}
		return true;
	}

	/**
	 * 点赞
	 * 
	 * @param uid
	 * @param goodsId
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public Boolean addLike(Long uid, String goodsId) {
		if (isLike(uid, goodsId)) {
			return true;
		}
		// 新增点赞
		TblUserLike userLike = new TblUserLike(uid, goodsId);
		baseMapper.insert(userLike);
		// 点赞数加一
		iInnerService.adjustPopularityRate(goodsId, 1);
		// 增加点赞列表
		setRedisUserLike(uid, goodsId, 0);
		return true;
	}

	/**
	 * 取消点赞
	 * 
	 * @param uid
	 * @param goodsId
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public Boolean delLike(Long uid, String goodsId) {
		if (!isLike(uid, goodsId)) {
			return true;
		}
		// 删除点赞
		Map<String, Object> delMap = new HashMap<>();
		delMap.put("app_user_id", uid);
		delMap.put("goods_id", goodsId);
		baseMapper.deleteByMap(delMap);
		// 点赞数减一
		iInnerService.adjustPopularityRate(goodsId, -1);
		// 取消点赞列表
		setRedisUserLike(uid, goodsId, 1);
		return true;
	}

	public void setRedisUserLike(Long uid, String goodsId, Integer status) {
		ExchangeCache cacheConfig = ExchangeCache.USER_LIKE_SET;
		if (Boolean.FALSE.equals(stringRedisTemplate.hasKey(cacheConfig.genKey(uid.toString())))) {
			return;
		}
		if (Objects.equals(status, 0)) {
			stringRedisTemplate.opsForSet().add(cacheConfig.genKey(uid.toString()), goodsId.toString());
			return;
		}
		stringRedisTemplate.opsForSet().remove(cacheConfig.genKey(uid.toString()), goodsId.toString());

	}

	/**
	 * 是否点赞
	 * 
	 * @param uid
	 * @param goodsId
	 * @return true 点赞 false 没有点赞
	 */

	@Override
	public Boolean isLike(Long uid, String goodsId) {
		LambdaQueryChainWrapper<TblUserLike> query = new LambdaQueryChainWrapper<>(baseMapper);
		query.eq(TblUserLike::getAppUserId, uid).eq(TblUserLike::getGoodsId, goodsId);
		TblUserLike userLike = baseMapper.selectOne(query.getWrapper());
		return userLike != null;
	}

	/**
	 * 处理 用户点赞
	 * 
	 * @param uid
	 * @return
	 */
	@Override
	public Set<String> getUserLikeCache(Long uid) {
		// 如果key 存在
		ExchangeCache cacheConfig = ExchangeCache.USER_LIKE_SET;
		if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(cacheConfig.genKey(uid.toString())))) {
			return stringRedisTemplate.opsForSet().members(cacheConfig.genKey(uid.toString()));
		}
		Set<String> userLike = getUserLike(uid);
		if (Objects.isNull(userLike) || userLike.isEmpty()) {
			return userLike;
		}
		stringRedisTemplate.opsForSet().add(cacheConfig.genKey(uid.toString()), userLike.toArray(new String[0]));
		stringRedisTemplate
				.expire(ExchangeCache.USER_LIKE_SET.genKey(uid.toString()), ExchangeCache.USER_LIKE_SET.ttl(), ExchangeCache.USER_LIKE_SET.timeUnit());
		return userLike;
	}

	@Override
	public Set<String> getUserLike(Long uid) {
		LambdaQueryChainWrapper<TblUserLike> query = new LambdaQueryChainWrapper<>(baseMapper);
		query.eq(TblUserLike::getAppUserId, uid).select(TblUserLike::getAppUserId, TblUserLike::getGoodsId);
		List<TblUserLike> list = query.list();
		Set<String> ids = list.stream().map(x -> x.getGoodsId().toString()).collect(Collectors.toCollection(HashSet::new));
		return ids;
	}

}
